package controleur;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import javax.swing.JFileChooser;

import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import metier.*;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import utiles.FourmizLogger;
import utiles.K;
import vue.VueCreationCarte;
import vue.VueModificationCarte;
import vue.VueParametrageSimulation;

public class ControllerCreationCarte extends ControllerUtile {

    protected VueCreationCarte vcc;
    protected VueParametrageSimulation vps;
    protected VueModificationCarte vmc;

    public ControllerCreationCarte(VueParametrageSimulation vps) {
        this.vps = vps;
        this.initFourmizFileSystem(); // Initialise le dossier ~/Fourmiz ainsi que les sous dossiers associés
    }

    public void newCarte() {
        FourmizLogger.debug(this, "Création d'une carte...");
        this.vcc = new VueCreationCarte(this);
    }

    public void editCarte(Carte c) {
        FourmizLogger.debug(this, "Modification de la carte " + c.getNom() + "...");
        this.vmc = new VueModificationCarte(this, c);
    }

    public boolean deleteCarte(Carte carte) {
        File f = new File(carte.getPath());
        return f.exists() && f.delete();
    }

    public void openCarte() {
        JFileChooser menu = new JFileChooser();

        FileNameExtensionFilter filter = new FileNameExtensionFilter("Carte (.xml)", "xml");

        menu.setFileHidingEnabled(false);
        menu.setFileFilter(filter);
        menu.setApproveButtonText("Ouvrir");
        menu.setDialogTitle(this.vps.getTitle());
        menu.setFileSelectionMode(JFileChooser.FILES_ONLY);

        int retour = menu.showOpenDialog(null);
        if (retour == JFileChooser.APPROVE_OPTION) {
            String path = menu.getSelectedFile().getAbsolutePath();
            File source = new File(path);
            if (!source.exists() || source.isDirectory()) //Très peu de chance d'arriver
            {
                JOptionPane.showMessageDialog(this.vps, "Le fichier de carte est introuvable ou incorrect");
            } else {
                File dest = new File(K.MAPS_FOLDER, source.getName());
                try {
                    boolean result = true;
                    if (dest.exists())// Si le fichier existe déjà, on le supprime
                    {
                        FourmizLogger.info(this, "Le fichier " + dest.toPath() + " existe déjà");
                        //Suppression du fichier
                        result = dest.delete();
                        FourmizLogger.info(this, "Suppression du fichier " + dest.toPath() + " :" + (result ? "OK" : "NOK"));
                        if (!result) {
                            JOptionPane.showMessageDialog(this.vps, "Impossible de supprimer le fichier " + dest.toPath());
                        }
                    }

                    if (result) //On ne copie que dans le cas où le fichier n'existe pas ou qu'il a correctement été supprimé
                    {
                        //Copie du fichier vers le repertoire ~/Fourmiz/Cartes
                        FourmizLogger.info(this, "Copie de " + source.toPath() + " vers " + dest.toPath());
                        Files.copy(source.toPath(), dest.toPath());
                    }

                } catch (IOException ex) {
                    FourmizLogger.error(this, ex);
                }
            }
        }
    }

    public void notifyMapCreated(Carte c) {
        this.vps.updateListeCarte();
        this.vps.selectCarte(c);

        if (this.vcc != null) {
            this.vcc.dispose();
        } else if (this.vmc != null) {
            this.vmc.dispose();
        } else {
            FourmizLogger.warn(this, "Une notification a été faite sur une vue non instanciée");
        }
    }

    public boolean createDocument(String nomCarte, Carte carte) {
        Document document = null;
        DocumentBuilderFactory fabrique = null;

        try {
            // Création du document
            fabrique = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = fabrique.newDocumentBuilder();
            document = builder.newDocument();

            // Racine
            Element carteNode = (Element) document.createElement("carte");
            carteNode.setAttribute("longueur", String.valueOf(K.LONG));
            carteNode.setAttribute("largeur", String.valueOf(K.LARG));
            document.appendChild(carteNode);

            // Nom de la carte
            Element nom = document.createElement("nom");
            nom.appendChild(document.createTextNode(nomCarte));
            carteNode.appendChild(nom);

            Element cases = document.createElement("cases");
            for (int y = 0; y < carte.getLongueur(); y++) {
                for (int x = 0; x < carte.getLargeur(); x++) {

                    Element cas = document.createElement("case");

                    cas.setAttribute("x", "" + x);
                    cas.setAttribute("y", "" + y);

                    // Laisser l'inversion de x et y car on parcours en ligne et non en colonne
                    ArrayList<metier.Element> elements = carte.getElements(new Position(x, y));

                    for (metier.Element elem : elements) {
                        String difficulte;
                        String qteNourriture;
                        Element elementNode;
                        Element diffNode;

                        switch (elem.getClass().toString()) {
                            case "class metier.Herbe":
                                Herbe herbe = (Herbe) elem;
                                difficulte = String.valueOf(herbe.getDifficulte());

                                elementNode = document.createElement("herbe");

                                diffNode = document.createElement("difficulte");
                                diffNode.appendChild(document.createTextNode(difficulte));
                                elementNode.appendChild(diffNode);

                                cas.appendChild(elementNode);
                                break;
                            case "class metier.Roche":
                                Roche roche = (Roche) elem;
                                difficulte = String.valueOf(roche.getDifficulte());

                                elementNode = document.createElement("roche");

                                diffNode = document.createElement("difficulte");
                                diffNode.appendChild(document.createTextNode(difficulte));
                                elementNode.appendChild(diffNode);

                                cas.appendChild(elementNode);
                                break;
                            case "class metier.Nouriturre":
                                Nouriturre nourriture = (Nouriturre) elem;
                                qteNourriture = String.valueOf(nourriture.getQuantiteNourritureDisponible());

                                elementNode = document.createElement("sourceNourriture");

                                diffNode = document.createElement("quantite");
                                diffNode.appendChild(document.createTextNode(qteNourriture));
                                elementNode.appendChild(diffNode);

                                cas.appendChild(elementNode);
                                break;
                        }
                    }

                    cases.appendChild(cas);
                }
            }

            carteNode.appendChild(cases);

            // write the content into xml file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(new File(K.MAPS_FOLDER, nomCarte + ".xml"));

			// Output to console for testing
            // StreamResult result = new StreamResult(System.out);
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            transformer.transform(source, result);

            return true;
        } catch (Exception e) {
            e.printStackTrace();

            return false;
        }

    }

}
